﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace Code4WP7SDK
{
    public class JsonHelper : IDisposable
    {
        #region Token Consts

        //JToken RootToken; 
        JToken _cursorToken;
        #endregion

        #region Construtor
        protected JsonHelper()
        {

        }
        public JsonHelper(string content)
            : this()
        {
            _cursorToken = JToken.Parse(content);
            //= RootToken 
        }
        #endregion

        #region Operation
        public virtual JsonHelper at(string node)
        {
            this.CheckNodeName(node);
            if (_cursorToken.HasValues)
            {
                _cursorToken = _cursorToken.SelectToken(node);
            }
            return this;
        }
        public virtual JsonHelper at(Int32 index)
        {
            if (_cursorToken.HasValues)
            {
                if (_cursorToken.HasValues)
                {
                    _cursorToken = _cursorToken[index];
                }
            }
            return this;
        }
        public virtual JsonHelper add(string node, object value)
        {
            this.CheckNodeName(node);
            if (_cursorToken != null)
            {
                JObject innerObj = new JObject();
                innerObj.Add(node, new JValue(value));
                _cursorToken.AddAfterSelf(innerObj);
            }
            return this;
        }
        public virtual JsonHelper set(string node, object value)
        {
            this.CheckNodeName(node);
            JToken innerToken = _cursorToken.SelectToken(node);
            if (innerToken != null)
            {
                this.remove(node);
            }
            JObject innerObj = _cursorToken as JObject;
            if (innerObj != null)
            {
                JValue objvalue = new JValue(value);
                innerObj.Add(node, objvalue);
            }
            return this;
        }
        public virtual T get<T>(string node)
        {
            CheckNodeName(node);
            JToken innerToken = _cursorToken.SelectToken(node);
            try
            {
                return innerToken.ToObject<T>();
            }
            catch
            {
                return default(T);
            }
        }
        public virtual JsonHelper remove(string node)
        {
            this.CheckNodeName(node);
            JToken innerToken = _cursorToken.SelectToken(node);
            if (innerToken != null)
            {
                innerToken.Parent.Remove();
            }
            return this;
        }
        public virtual JsonHelper rename(string oldnode, string newnode)
        {
            this.CheckNodeName(oldnode);
            this.CheckNodeName(newnode);

            return this;
        }
        public virtual JsonHelper up()
        {
            _cursorToken = _cursorToken.Parent;
            return this;
        }
        public virtual Int32 Count()
        {
            if (_cursorToken.HasValues)
            {
                JArray array = _cursorToken as JArray;
                if (array == null)
                {
                    return 0;
                }
                else
                {
                    return array.Count;
                }
            }
            else
            {
                return 0;
            }
        }
        public static JsonHelper create()
        {
            JsonHelper json = new JsonHelper();
            return json;
        }
        #endregion

        #region Private Methods
        private void CheckNodeName(string node)
        {
            if (string.IsNullOrEmpty(node))
            {
                throw new Exception("node name is required.");
            }
        }
        #endregion

        #region Static Methods
        public static string Serliazer(object obj)
        {
            JToken token = JToken.FromObject(obj);
            return token.ToString();
        }
        public static T Deserlizaer<T>(string obj)
        {
            JToken token = JToken.Parse(obj);
            return token.ToObject<T>();
        }
        #endregion

        #region Public

        public override string ToString()
        {
            return _cursorToken.Root.ToString(Formatting.None, null);
        }
        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            //RootToken = null; 
            _cursorToken = null;
            GC.Collect();
        }
        #endregion 
    }
}
